#ifndef __EVENTLOOP_H__
#define __EVENTLOOP_H__

#include <sys/epoll.h>
#include <vector>
#include <map>
#include <memory>
#include <iostream>
#include <functional>

using std::vector;
using std::map;
using std::shared_ptr;
using std::cout;
using std::endl;
using std::function;
using std::bind;

class Acceptor;//前向声明
class TcpConnection;

using TcpConnectionPtr = shared_ptr<TcpConnection>;
//为了表明三个事件都与连接TcpConnection相关
using TcpConnectionCallback = function<void(const TcpConnectionPtr &con)>;

class EventLoop
{

public:
    EventLoop(Acceptor &acceptor);
    ~EventLoop();

    //事件循环
    void loop();
    void unloop();

    //三个回调函数的注册
    //三个回调函数本来是与TcpConnection相关的，但是现在从类外
    //传递进来的时候，只能知道的是EventLoop，然后通过EventLoop
    //传递给TcpConnection
    void setConnectionCallback(TcpConnectionCallback &&cb);
    void setMessageCallback(TcpConnectionCallback &&cb);
    void setCloseCallback(TcpConnectionCallback &&cb);

private:
    //里面封装epoll_wait
    void waitEpollFd();
    //处理新的连接请求
    void handleNewConnection();
    //处理消息的发送
    void handleMessage(int fd);
    //epfd的创建
    int createEpollFd();
    //监听或者删除文件描述符
    void addEpollReadFd(int fd);
    void delEpollReadFd(int fd);

private:
    int _epfd;//是epoll_create创建文件描述符
    bool _isLooping;//循环的标志位
    Acceptor &_acceptor;//会调用accept函数
    vector<struct epoll_event> _evtList;//存放满足条件的事件
    map<int, TcpConnectionPtr> _conns;//存放的是文件描述符与TcpConnection的键值对

    TcpConnectionCallback _onConnectionCb;
    TcpConnectionCallback _onMessageCb;
    TcpConnectionCallback _onCloseCb;
};

#endif
